


class Field:
    """字段基类，用于描述数据库字段"""
    def __init__(self, name=None, primary_key=False, nullable=True):
        self.name = name
        self.primary_key = primary_key
        self.nullable = nullable

    def __set_name__(self, owner, name):
        # 描述符协议方法，自动设置字段名
        # 当Field实例作为类属性被创建时自动调用，用于设置字段名
        if self.name is None:
            self.name = name


class IntegerField(Field):
    """整数字段"""
    pass


class StringField(Field):
    """字符串字段"""
    def __init__(self, max_length=255, **kwargs):
        super().__init__(**kwargs)
        self.max_length = max_length


class ModelMeta(type):
    # 模型元类，负责创建Model类时收集字段信息 ===   用于在创建类（而不是实例）时进行定制
    # 当定义 User 类时，ModelMeta.__new__ 会被调用
    def __new__(cls, name, bases, namespace):
        #  name  cls  的名字：
        #  bases  cls 的父类
        #  namespace 类定义过程中动态收集类体内的所有成员（包括方法、类变量、注解等）
        # 排除对Model基类的处理
        if name == 'Model':
            return super().__new__(cls, name, bases, namespace)

        # 收集字段信息
        fields = {}
        primary_key = None
        for key, value in namespace.items():
            if isinstance(value, Field):  # 只过滤出Field 相关的字段属性，其他都会被排除在外
                fields[key] = value
                if value.primary_key:
                    if primary_key is not None:
                        raise ValueError(f"Multiple primary keys in {name}")
                    primary_key = key

        if not primary_key:
            raise ValueError(f"No primary key defined in {name}")

        # 创建类并添加元数据
        new_cls = super().__new__(cls, name, bases, namespace)
        new_cls._fields = fields
        new_cls._primary_key = primary_key
        new_cls._table = namespace.get('__table__', name.lower())

        # 优化内存使用  并  限制实例可以动态添加的属性
        # 限制实例只能拥有 __slots__ 中指定的属性，不能动态添加其他属性。
        # 节省内存：对于大量实例的类，使用 __slots__ 可以避免每个实例都维护一个 __dict__（字典），从而减少内存占用
        new_cls.__slots__ = tuple(fields.keys()) + ('_dirty',)

        # 元类的 __new__ 必须返回一个类对象（type 的实例），否则会导致类无法正确创建。
        return new_cls


class Model(metaclass=ModelMeta):
    """模型基类"""
    def __init__(self, **kwargs):
        # 初始化实例属性
        self._dirty = set()
        for field in self._fields:
            setattr(self, field, kwargs.get(field))

    def __setattr__(self, name, value):
        # 跟踪修改过的字段
        if name in self._fields:
            self._dirty.add(name)
        super().__setattr__(name, value)

    def save(self):
        """模拟保存到数据库"""
        if not self._dirty:
            print(f"No changes to save for {self.__class__.__name__}")
            return

        # 构建SQL语句
        fields = ', '.join(self._dirty)
        values = ', '.join(
            repr(getattr(self, field))
            for field in self._dirty
        )

        pk_value = getattr(self, self._primary_key)
        if pk_value is None:
            # 插入新记录
            sql = f"INSERT INTO {self._table} ({fields}) VALUES ({values})"
        else:
            # 更新现有记录
            updates = ', '.join(
                f"{field}={repr(getattr(self, field))}"
                for field in self._dirty
            )
            sql = f"UPDATE {self._table} SET {updates} WHERE {self._primary_key}={pk_value}"

        print(f"Executing SQL: {sql}")
        self._dirty.clear()

    @classmethod
    def create_table(cls):
        """模拟创建数据库表"""
        columns = []
        print("-----> ", cls._fields)
        for name, field in cls._fields.items():
            column = f"{name} "
            if isinstance(field, IntegerField):
                column += "INTEGER"
            elif isinstance(field, StringField):
                column += f"VARCHAR({field.max_length})"

            if field.primary_key:
                column += " PRIMARY KEY"
            if not field.nullable:
                column += " NOT NULL"

            columns.append(column)

        sql = f"CREATE TABLE {cls._table} (\n  " + ",\n  ".join(columns) + "\n)"
        print(f"Executing SQL: {sql}")

    def __repr__(self):
        fields_str = ', '.join(
            f"{k}={repr(getattr(self, k))}"
            for k in self._fields
        )
        # fields_str:  id=1, name='Jack', email='new_email@example.com', age=31
        print("---------------__repr__------------------", fields_str)
        # <User id=1, name='Jack', email='new_email@example.com', age=31>
        return f"<{self.__class__.__name__} {fields_str}>"


# 使用示例
class User(Model):
    """用户模型"""
    __table__ = 'users'  # 自定义表名

    id = IntegerField(primary_key=True)
    name = StringField(max_length=50, nullable=False)
    email = StringField(max_length=100)
    age = IntegerField()

    """ user._fields
    {
    'id': <__main__.IntegerField object at 0x0000016F8B99B070>, 
    'name': <__main__.StringField object at 0x0000016F8B99B3D0>, 
    'email': <__main__.StringField object at 0x0000016F8BBD92B0>, 
    'age': <__main__.IntegerField object at 0x0000016F8BBD9940>
    }
    """

# 创建数据库表
User.create_table()

# 创建用户实例
user = User(id=1, name="Alice", email="alice@example.com", age=30)
print(user)  # <User id=1, name='Alice', email='alice@example.com', age=30>
user.save()
# 修改属性
user.age = 31
user.email = "new_email@example.com"

# 保存到数据库
user.save()